/*
	Yelo: Open Sauce SDK
		Halo 1 (CE) Edition

	See license\OpenSauce\Halo1_CE for specific license information
*/


namespace Yelo
{
	namespace Objects
	{
		namespace Animations
		{
#if PLATFORM_IS_DEDI
			void Initialize()	{}
			void Dispose()		{}
#else

			// Fixes the animation keyframe event switch so that every animation state can use 
			// the primary and secondary keyframe values, and we can call our own functions on those keyframes
			static void FixAnimationKeyFrameEventSwitch()
			{
				static void* jmp_table[44] = {
					CAST_PTR(void*, 0x5692B7),			// 0 = idle
					CAST_PTR(void*, 0x5692B7),			// 1 = gesture
					CAST_PTR(void*, 0x5692B7),			// 2 = turn_left
					CAST_PTR(void*, 0x5692B7),			// 3 = turn_right
					CAST_PTR(void*, 0x5692B7),			// 4 = move_front
					CAST_PTR(void*, 0x5692B7),			// 5 = move_back
					CAST_PTR(void*, 0x5692B7),			// 6 = move_left
					CAST_PTR(void*, 0x5692B7),			// 7 = move_right
					CAST_PTR(void*, 0x5692B7),			// 8 = stunned_front
					CAST_PTR(void*, 0x5692B7),			// 9 = stunned_back
					CAST_PTR(void*, 0x5692B7),			// 10 = stunned_left
					CAST_PTR(void*, 0x5692B7),			// 11 = stunned_right
					CAST_PTR(void*, 0x5692B7),			// 12 = slide_front
					CAST_PTR(void*, 0x5692B7),			// 13 = slide_back
					CAST_PTR(void*, 0x5692B7),			// 14 = slide_left
					CAST_PTR(void*, 0x5692B7),			// 15 = slide_right
					CAST_PTR(void*, 0x5692B7),			// 16 = ready
					CAST_PTR(void*, 0x5692B7),			// 17 = put_away
					CAST_PTR(void*, 0x5692B7),			// 18 = aim_still
					CAST_PTR(void*, 0x5692B7),			// 19 = aim_move
					CAST_PTR(void*, 0x5692B7),			// 20 = airborne
					CAST_PTR(void*, 0x5692B7),			// 21 = land_soft
					CAST_PTR(void*, 0x5692B7),			// 22 = land_hard
					CAST_PTR(void*, 0x5692B7),			// 23 = unknown23
					CAST_PTR(void*, 0x5692B7),			// 24 = airborne_dead
					CAST_PTR(void*, 0x5692B7),			// 25 = landing_dead
					CAST_PTR(void*, 0x5692B7),			// 26 = seat_enter
					CAST_PTR(void*, 0x5692B7),			// 27 = seat_exit
					CAST_PTR(void*, 0x5692B7),			// 28 = custom_animation
					CAST_PTR(void*, 0x5692B7),			// 29 = impulse
					CAST_PTR(void*, 0x5690C0),			// 30 = melee
					CAST_PTR(void*, 0x5690C0),			// 31 = melee_airborne
					CAST_PTR(void*, 0x5692B7),			// 32 = melee_continuous
					CAST_PTR(void*, 0x5690B0),			// 33 = throw_grenade
					CAST_PTR(void*, 0x5692B7),			// 34 = resurrect_front
					CAST_PTR(void*, 0x5692B7),			// 35 = resurrect_back
					CAST_PTR(void*, 0x5692B7),			// 36 = feeding
					CAST_PTR(void*, 0x5692B7),			// 37 = surprise_front
					CAST_PTR(void*, 0x5692B7),			// 38 = surprise_back
					CAST_PTR(void*, 0x5692B7),			// 39 = leap_start
					CAST_PTR(void*, 0x5692B7),			// 40 = leap_airborne
					CAST_PTR(void*, 0x5690C0),			// 41 = leap_melee
					CAST_PTR(void*, 0x5692B7),			// 42 = unknown42
					CAST_PTR(void*, 0x5692B7),			// 43 = berserk
				};
				// nullify indirect table referencing, allows every animation state to be dealt with in the switch
				// this requires every unused animation state to jump to the default case
				static const byte k_null_bytes_index[3] = { 
					Enums::_x86_opcode_nop, Enums::_x86_opcode_nop,
					Enums::_x86_opcode_nop 
				};
				static const byte k_null_bytes_pointer[7] = { 
					Enums::_x86_opcode_nop, Enums::_x86_opcode_nop,
					Enums::_x86_opcode_nop, Enums::_x86_opcode_nop,
					Enums::_x86_opcode_nop, Enums::_x86_opcode_nop,
					Enums::_x86_opcode_nop
				};

				Memory::WriteMemory(GET_FUNC_VPTR(ANIMATION_KEYFRAME_EVENT_INDIRECT_TABLE_INDEX_NULL), k_null_bytes_index, sizeof(k_null_bytes_index));
				Memory::WriteMemory(GET_FUNC_VPTR(ANIMATION_KEYFRAME_EVENT_INDIRECT_TABLE_POINTER_NULL), k_null_bytes_pointer, sizeof(k_null_bytes_pointer));

				// Overwrite the jmp table references with our own
				GET_PTR(AnimationKeyFrameEventJmpTableCount) = sizeof(jmp_table);
				GET_PTR(AnimationKeyFrameEventJmpTablePtr) = jmp_table;
			}

			void Initialize()
			{
				FixAnimationKeyFrameEventSwitch();
			}

			void Dispose()
			{
			}
			
#endif
		};
	};
};